package com.recipedb.recipedb.controller;

import com.recipedb.recipedb.entity.User;
import com.recipedb.recipedb.service.UserService;
import com.recipedb.recipedb.security.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

@RestController
@RequestMapping("/api/users")
public class UserAuthController {

    private static final String INVITE_CODE = "WCHwch"; // 自定义邀请码

    private final UserService userService;
    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(6);

    // 用户名允许中文、字母、数字、下划线
    private static final Pattern USERNAME_PATTERN = Pattern.compile("^[\\u4e00-\\u9fa5a-zA-Z0-9_]{2,20}$");
    // 密码允许ASCII可打印字符，长度 6-20
    private static final Pattern PASSWORD_PATTERN = Pattern.compile("^[\\x21-\\x7E]{6,20}$");

    @Autowired
    public UserAuthController(UserService userService) {
        this.userService = userService;
    }

    private boolean isUsernameValid(String username) {
        return username != null && USERNAME_PATTERN.matcher(username).matches();
    }

    private boolean isPasswordValid(String password) {
        return password != null && PASSWORD_PATTERN.matcher(password).matches();
    }

    @PostMapping("/register")
    public ResponseEntity<Map<String, Object>> register(@RequestBody Map<String, String> payload) {
        String username = payload.get("username");
        String password = payload.get("password");
        String inviteCode = payload.get("inviteCode");

        Map<String, Object> resp = new HashMap<>();

        // 校验用户名和密码
        if (!isUsernameValid(username)) {
            resp.put("message", "用户名只能包含中文、字母、数字、下划线，长度2-20");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
        }
        if (!isPasswordValid(password)) {
            resp.put("message", "密码长度6-20，只能包含可打印ASCII字符");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
        }

        // 校验邀请码
        if (!INVITE_CODE.equals(inviteCode)) {
            resp.put("message", "邀请码错误");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(resp);
        }

        // 检查用户名是否存在
        if (userService.existsByUsername(username)) {
            resp.put("message", "用户名已存在");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.CONFLICT).body(resp);
        }

        // 创建用户
        User user = new User();
        user.setUsername(username);
        user.setPasswordHash(passwordEncoder.encode(password));
        user.setInviteCode(inviteCode);
        user.setCreatedAt(LocalDateTime.now());

        userService.save(user);

        User savedUser = userService.findByUsername(username);

        resp.put("message", "注册成功");
        resp.put("username", savedUser.getUsername());
        resp.put("uid", savedUser.getUid());
        resp.put("userId", savedUser.getId());
        resp.put("createdAt", savedUser.getCreatedAt());

        return ResponseEntity.status(HttpStatus.CREATED).body(resp);
    }

    @PostMapping("/login")
    public ResponseEntity<Map<String, Object>> login(@RequestBody Map<String, String> payload) {
        String username = payload.get("username");
        String password = payload.get("password");

        Map<String, Object> resp = new HashMap<>();

        if (username == null || password == null) {
            resp.put("message", "用户名或密码不能为空");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
        }

        User user = userService.findByUsername(username);
        if (user == null) {
            resp.put("message", "用户不存在");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(resp);
        }

        if (!passwordEncoder.matches(password, user.getPasswordHash())) {
            resp.put("message", "密码错误");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(resp);
        }

        String token = JwtUtil.generateToken(username);

        resp.put("message", "登录成功");
        resp.put("token", token);
        resp.put("username", user.getUsername());
        resp.put("uid", user.getUid());
        resp.put("userId", user.getId());

        return ResponseEntity.ok(resp);
    }

    @PostMapping("/change-password")
    public ResponseEntity<Map<String, Object>> changePassword(
            @RequestHeader("Authorization") String authHeader,
            @RequestBody Map<String, String> payload) {

        Map<String, Object> resp = new HashMap<>();

        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            resp.put("message", "缺少有效的认证信息");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(resp);
        }

        String token = authHeader.substring(7);
        String tokenUsername = JwtUtil.validateToken(token);

        if (tokenUsername == null) {
            resp.put("message", "Token 无效或已过期");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(resp);
        }

        String username = payload.get("username");
        String currentPassword = payload.get("currentPassword");
        String newPassword = payload.get("newPassword");

        if (username == null || currentPassword == null || newPassword == null) {
            resp.put("message", "用户名、当前密码和新密码不能为空");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
        }

        if (!isPasswordValid(newPassword)) {
            resp.put("message", "新密码长度6-20，只能包含可打印ASCII字符");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
        }

        if (!tokenUsername.equals(username)) {
            resp.put("message", "无权修改其他用户的密码");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(resp);
        }

        if (currentPassword.equals(newPassword)) {
            resp.put("message", "新密码不能与当前密码相同");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
        }

        User user = userService.findByUsername(username);
        if (user == null) {
            resp.put("message", "用户不存在");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(resp);
        }

        if (!passwordEncoder.matches(currentPassword, user.getPasswordHash())) {
            resp.put("message", "当前密码错误");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(resp);
        }

        user.setPasswordHash(passwordEncoder.encode(newPassword));
        userService.save(user);

        resp.put("message", "密码修改成功");
        resp.put("username", username);
        resp.put("userId", user.getId());

        return ResponseEntity.ok(resp);
    }

    @PostMapping("/change-username")
    public ResponseEntity<Map<String, Object>> changeUsername(
            @RequestHeader("Authorization") String authHeader,
            @RequestBody Map<String, String> payload) {

        Map<String, Object> resp = new HashMap<>();

        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            resp.put("message", "缺少有效的认证信息");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(resp);
        }

        String token = authHeader.substring(7);
        String tokenUsername = JwtUtil.validateToken(token);

        if (tokenUsername == null) {
            resp.put("message", "Token 无效或已过期");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(resp);
        }

        String currentUsername = payload.get("currentUsername");
        String newUsername = payload.get("newUsername");

        if (currentUsername == null || newUsername == null) {
            resp.put("message", "当前用户名和新用户名不能为空");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
        }

        if (!isUsernameValid(newUsername)) {
            resp.put("message", "新用户名只能包含中文、字母、数字、下划线，长度2-20");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
        }

        if (!tokenUsername.equals(currentUsername)) {
            resp.put("message", "无权修改其他用户的用户名");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(resp);
        }

        if (currentUsername.equals(newUsername)) {
            resp.put("message", "新用户名不能与当前用户名相同");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
        }

        if (userService.existsByUsername(newUsername)) {
            resp.put("message", "用户名已存在");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.CONFLICT).body(resp);
        }

        try {
            User user = userService.findByUsername(currentUsername);
            if (user == null) {
                resp.put("message", "用户不存在");
                resp.put("userId", null);
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(resp);
            }

            User updatedUser = userService.updateUsername(user.getId(), newUsername);
            String newToken = JwtUtil.generateToken(newUsername);

            resp.put("message", "用户名修改成功");
            resp.put("username", updatedUser.getUsername());
            resp.put("userId", updatedUser.getId());
            resp.put("token", newToken);

            return ResponseEntity.ok(resp);

        } catch (Exception e) {
            resp.put("message", "修改用户名时发生错误");
            resp.put("userId", null);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resp);
        }
    }
    /**
     * 重置密码接口（通过用户名 + 邀请码）
     */
    @PostMapping("/reset-password")
    public ResponseEntity<Map<String, Object>> resetPassword(@RequestBody Map<String, String> payload) {
        String username = payload.get("username");
        String inviteCode = payload.get("inviteCode");
        String newPassword = payload.get("newPassword");

        // 参数校验
        if (username == null || inviteCode == null || newPassword == null) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(Map.of(
                            "message", "用户名、邀请码和新密码不能为空",
                            "userId", null
                    ));
        }

        // 检查新密码格式
        if (newPassword.length() < 6 || newPassword.length() > 20
                || !newPassword.chars().allMatch(c -> c >= 32 && c <= 126)) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(Map.of(
                            "message", "新密码长度6-20，只能包含可打印ASCII字符",
                            "userId", null
                    ));
        }

        // 查找用户
        User user = userService.findByUsername(username);
        if (user == null) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                    .body(Map.of(
                            "message", "用户不存在",
                            "userId", null
                    ));
        }

        // 校验邀请码
        if (!inviteCode.equals(user.getInviteCode())) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(Map.of(
                            "message", "邀请码错误",
                            "userId", user.getId()
                    ));
        }

        // 更新密码
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(6);
        user.setPasswordHash(passwordEncoder.encode(newPassword));
        userService.save(user);

        return ResponseEntity.ok(Map.of(
                "message", "密码重置成功",
                "username", user.getUsername(),
                "userId", user.getId()
        ));
    }

}
